package cn.ycc1.boot3video.video;

import lombok.Data;

import java.util.*;
import java.util.concurrent.*;

public class SwitchableHlsGeneratorBak {

    @Data
    // 内部静态类，确保方法可访问
    public static class VariantStream {
        // 必须添加getter方法
        private String uri;
        private int bandwidth;
        private String resolution;
        private String codecs;
        private String name;

        public VariantStream(String uri, int bandwidth, String resolution, String codecs, String name) {
            this.uri = uri;
            this.bandwidth = bandwidth;
            this.resolution = resolution;
            this.codecs = codecs;
            this.name = name;
        }

    }

    public static void main(String[] args) {
        String inputVideo = "/path/to/source.mp4";
        String outputDir = "/path/to/hls_output";

        // 1. 生成多清晰度HLS流
        boolean success = generateMultiQualityHls(inputVideo, outputDir);

        if (success) {
            // 2. 生成支持切换的主播放列表
            generateSwitchableMasterPlaylist(outputDir);
            System.out.println("支持切换清晰度的HLS流生成完成！");
        }
    }

    /**
     * 生成支持切换的主播放列表
     */
    public static void generateSwitchableMasterPlaylist(String outputDir) {
        List<VariantStream> variants = Arrays.asList(
                new VariantStream("1080p.m3u8", 2000000, "1920x1080",
                        "avc1.640028,mp4a.40.2", "超清"),
                new VariantStream("720p.m3u8", 1000000, "1280x720",
                        "avc1.64001f,mp4a.40.2", "高清"),
                new VariantStream("480p.m3u8", 500000, "854x480",
                        "avc1.64001e,mp4a.40.2", "标清"),
                new VariantStream("360p.m3u8", 250000, "640x360",
                        "avc1.64001e,mp4a.40.2", "流畅")
        );

        String masterContent = buildMasterPlaylistWithSwitching(variants);

        try {
            saveToFile(masterContent, outputDir + "/master.m3u8");
            System.out.println("主播放列表已生成，支持中途切换清晰度");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 构建支持切换的主播放列表
     */
    public static String buildMasterPlaylistWithSwitching(List<VariantStream> variants) {
        StringBuilder m3u8 = new StringBuilder();

        m3u8.append("#EXTM3U\n");
        m3u8.append("#EXT-X-VERSION:3\n");
        m3u8.append("## 此主播放列表支持播放中途切换清晰度\n");
        m3u8.append("## 播放器会根据网络条件自动切换，用户也可手动选择\n\n");

        // 按带宽降序排列（推荐）
        variants.sort((v1, v2) -> Integer.compare(v2.getBandwidth(), v1.getBandwidth()));

        for (VariantStream variant : variants) {
            m3u8.append("#EXT-X-STREAM-INF:")
                    .append("BANDWIDTH=").append(variant.getBandwidth())
                    .append(",RESOLUTION=").append(variant.getResolution())
                    .append(",CODECS=\"").append(variant.getCodecs()).append("\"");

            // 添加NAME参数便于用户识别
            if (variant.getName() != null) {
                m3u8.append(",NAME=\"").append(variant.getName()).append("\"");
            }

            m3u8.append("\n")
                    .append(variant.getUri())
                    .append("\n\n");
        }

        return m3u8.toString();
    }

    /**
     * 生成多清晰度HLS流（确保时间轴对齐）
     */
    public static boolean generateMultiQualityHls(String inputPath, String outputDir) {
        ExecutorService executor = Executors.newFixedThreadPool(4);

        try {
            // 关键：所有清晰度使用相同的编码参数确保时间轴对齐
            List<Future<Boolean>> futures = new ArrayList<>();

            futures.add(executor.submit(() ->
                    encodeQuality(inputPath, outputDir, "1080p", 2000, "1920:1080", "128k")));
            futures.add(executor.submit(() ->
                    encodeQuality(inputPath, outputDir, "720p", 1000, "1280:720", "96k")));
            futures.add(executor.submit(() ->
                    encodeQuality(inputPath, outputDir, "480p", 500, "854:480", "64k")));
            futures.add(executor.submit(() ->
                    encodeQuality(inputPath, outputDir, "360p", 250, "640:360", "64k")));

            // 等待所有编码任务完成
            for (Future<Boolean> future : futures) {
                if (!future.get()) {
                    return false;
                }
            }

            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            executor.shutdown();
        }
    }

    /**
     * 编码单个清晰度（关键：确保时间轴对齐）
     */
    private static boolean encodeQuality(String inputPath, String outputDir,
                                         String quality, int videoBitrate,
                                         String resolution, String audioBitrate) {
        try {
            String[] commands = {
                    "ffmpeg", "-i", inputPath,
                    "-c:v", "libx264",
                    "-c:a", "aac",
                    "-b:v", videoBitrate + "k",
                    "-maxrate", (int)(videoBitrate * 1.07) + "k",
                    "-bufsize", (int)(videoBitrate * 1.5) + "k",
                    "-b:a", audioBitrate,

                    // 关键参数：确保时间轴对齐，支持无缝切换
                    "-g", "48",                    // GOP大小：48帧
                    "-keyint_min", "48",           // 最小关键帧间隔
                    "-sc_threshold", "0",          // 禁用场景切换检测
                    "-r", "24",                    // 固定帧率

                    "-vf", "scale=" + resolution,
                    "-hls_time", "4",              // 所有清晰度切片时长一致
                    "-hls_list_size", "0",
                    "-hls_playlist_type", "vod",
                    "-hls_segment_filename",
                    outputDir + "/" + quality + "_%03d.ts",
                    outputDir + "/" + quality + ".m3u8"
            };

            Process process = Runtime.getRuntime().exec(commands);
            int exitCode = process.waitFor();

            if (exitCode == 0) {
                System.out.println(quality + " 编码成功，支持无缝切换");
                return true;
            } else {
                System.err.println(quality + " 编码失败");
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 测试切换功能的HTML页面生成
     */
    public static void generateTestHtml(String outputDir) {
        String html = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>HLS清晰度切换测试</title>
            <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
        </head>
        <body>
            <h2>HLS清晰度切换测试</h2>
            <video id="video" controls width="800"></video>
            <div>
                <button onclick="switchQuality('1080p.m3u8')">超清 (1080p)</button>
                <button onclick="switchQuality('720p.m3u8')">高清 (720p)</button>
                <button onclick="switchQuality('480p.m3u8')">标清 (480p)</button>
                <button onclick="switchQuality('360p.m3u8')">流畅 (360p)</button>
                <button onclick="switchQuality('master.m3u8')">自动适应</button>
            </div>
            <div id="status">准备播放...</div>

            <script>
                const video = document.getElementById('video');
                const status = document.getElementById('status');
                let hls = new Hls();
                
                // 初始加载主播放列表
                loadMasterPlaylist();
                
                function loadMasterPlaylist() {
                    hls.loadSource('master.m3u8');
                    hls.attachMedia(video);
                    status.textContent = '已加载主播放列表，支持自动切换';
                    
                    hls.on(Hls.Events.MANIFEST_PARSED, function() {
                        console.log('可用的清晰度:', hls.levels);
                    });
                }
                
                function switchQuality(qualityUrl) {
                    const currentTime = video.currentTime;
                    const isPaused = video.paused;
                    
                    status.textContent = `切换到: ${qualityUrl}, 时间点: ${currentTime.toFixed(2)}s`;
                    
                    if (qualityUrl === 'master.m3u8') {
                        // 切换回主播放列表（自动适应）
                        hls.destroy();
                        hls = new Hls();
                        loadMasterPlaylist();
                    } else {
                        // 手动切换到指定清晰度
                        hls.loadSource(qualityUrl);
                        hls.attachMedia(video);
                    }
                    
                    // 恢复播放位置
                    video.currentTime = currentTime;
                    if (!isPaused) {
                        video.play().catch(e => console.log('播放失败:', e));
                    }
                }
                
                // 监听清晰度切换事件
                hls.on(Hls.Events.LEVEL_SWITCHED, function(event, data) {
                    console.log('清晰度切换:', data);
                    status.textContent = `已切换到: ${hls.levels[data.level].height}p`;
                });
            </script>
        </body>
        </html>
        """;

        try {
            saveToFile(html, outputDir + "/test.html");
            System.out.println("测试页面已生成: " + outputDir + "/test.html");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void saveToFile(String content, String filePath) throws Exception {
        try (java.io.FileWriter writer = new java.io.FileWriter(filePath)) {
            writer.write(content);
        }
    }

//    static class VariantStream {
//        String uri; int bandwidth; String resolution; String codecs; String name;
//        VariantStream(String u, int b, String r, String c, String n) {
//            uri = u; bandwidth = b; resolution = r; codecs = c; name = n;
//        }
//    }
}
